/**
 *  Copyright (c) 2010-2011, Monash e-Research Centre
 * (Monash University, Australia)
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 * * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *        documentation and/or other materials provided with the distribution.
 * * Neither the name of the Monash University nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY 
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
package au.edu.monash.its.confluence.plugins;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.httpclient.NameValuePair;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HTTP;

public class PDFcreator {
	
	public static DefaultHttpClient useTrustingTrustManager(DefaultHttpClient httpClient) throws NoSuchAlgorithmException, KeyManagementException
	{
			// First create a trust manager that won't care.
			X509TrustManager trustManager = new X509TrustManager()
			{	 
				public java.security.cert.X509Certificate[] getAcceptedIssuers()
				{
					// Don't do anything.
					return null;
				}

				public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1) throws CertificateException {
					// TODO Auto-generated method stub
					
				}

				public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1) throws CertificateException {
					// TODO Auto-generated method stub
					
				}
			};
	 
			// Now put the trust manager into an SSLContext.
			SSLContext sslcontext = SSLContext.getInstance("TLS");
			sslcontext.init(null, new TrustManager[] { trustManager }, null);
	 
			// Use the above SSLContext to create your socket factory
			// (I found trying to extend the factory a bit difficult due to a
			// call to createSocket with no arguments, a method which doesn't
			// exist anywhere I can find, but hey-ho).
			
			SSLSocketFactory socketFactory = new SSLSocketFactory(sslcontext);

			socketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 
	 
			// If you want a thread safe client, use the ThreadSafeConManager, but
			// otherwise just grab the one from the current client, and get hold of its
			// schema registry. THIS IS THE KEY THING.
			ClientConnectionManager ccm = httpClient.getConnectionManager();
			SchemeRegistry schemeRegistry = ccm.getSchemeRegistry();
	 
			// Register our new socket factory with the typical SSL port and the
			// correct protocol name.
			schemeRegistry.register(new Scheme("https", socketFactory, 443));
			
			// Finally, apply the ClientConnectionManager to the Http Client
			// or, as in this example, create a new one.
			return new DefaultHttpClient(ccm, httpClient.getParams());
	}		

	public static File getPDF(URL url, String pageId, String username, String password)
			throws IllegalStateException, IOException, KeyManagementException, NoSuchAlgorithmException {
		InputStream contentStream = null;	

		DefaultHttpClient httpClient = new DefaultHttpClient();
		httpClient = useTrustingTrustManager(httpClient);
		
		// log in
		HttpPost httpPost = new HttpPost(url.toExternalForm() + "/dologin.action");
		System.out.println(httpPost.getURI());
		
		// HTTP parameters stores header etc.
		HttpParams params = new BasicHttpParams();

		httpPost.setParams(params);

		List<BasicNameValuePair> nameValuePairs = new ArrayList<BasicNameValuePair>(3);
		nameValuePairs.add(new BasicNameValuePair("os_username", username));
		nameValuePairs.add(new BasicNameValuePair("os_password", password));

		httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8));
		HttpResponse response = httpClient.execute(httpPost);
		response.getEntity().consumeContent();
		// get plugin redirect location
		
		String pluginDestination = "/spaces/flyingpdf/pdfpageexport.action?pageId="
			+ pageId;		
		
		HttpResponse response2 = httpClient.execute(new HttpPost(url.toExternalForm() + pluginDestination));

        String redirectLocation = "";
        Header[] locations = response2.getHeaders("Location");

        for (Header location : locations)
        {
        	redirectLocation = location.getValue();
        }
        
        
        
        System.out.println(redirectLocation);
        response2.getEntity().consumeContent();
		// execute pdf download 
		HttpResponse response3 = httpClient.execute(new HttpGet(redirectLocation));	
		response3.addHeader("Content-Type", "application/octet-stream");
		
		HttpEntity entity = response3.getEntity();
		if (entity != null) {
			// File pdfFile = new File("confluencePDFoutput.pdf");
			// writeToFile(entity.getContent(), pdfFile);
			contentStream = entity.getContent();
		}

		File temp = File.createTempFile("hoatemppdf", ".pdf");

		// Delete temp file when program exits.
		temp.deleteOnExit();

		writeToFile(contentStream, temp);
		httpClient.getConnectionManager().shutdown();

		return temp;

	}

	public static void writeToFile(InputStream input, File file)
			throws IOException {
		OutputStream output = null;
		byte[] buffer = new byte[1024];

		try {
			System.out.println("Downloading file...");
			output = new FileOutputStream(file);
			for (int length; (length = input.read(buffer)) > 0;) {
				output.write(buffer, 0, length);
			}
			System.out.println("File successfully downloaded!");
		} finally {
			if (output != null)
				try {
					output.close();
				} catch (IOException logOrIgnore) {
				}
			if (input != null)
				try {
					input.close();
				} catch (IOException logOrIgnore) {
				}
		}
	}

}
